#define PY_SSIZE_T_CLEAN
#include <Python.h>

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/spi/spidev.h>
#include <linux/types.h>
#include <sys/ioctl.h>
#include <linux/ioctl.h>

#include "sx1262/sx126x-hal.h"

PacketParams_t PacketParams;
PacketStatus_t PacketStatus;

ModulationParams_t modulationParams;

#define RF_FREQUENCY  434000000 // Hz

#define TX_OUTPUT_POWER   14 //The range of the output power is [-18..+13] dBm

#define TX_TIMEOUT_VALUE                            0xFFFF // ms
//#define RX_TIMEOUT_VALUE                            12800 // 200ms
#define RX_TIMEOUT_VALUE                            6400 // 100ms

const uint16_t RxIrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT;
const uint16_t TxIrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT;

int  spi_sx = -1;

static PyObject * Open(PyObject *self, PyObject *args)
{
    uint32_t    max_speed_hz = 10000000;
    uint8_t     mode;

	Reset();

	// 初始化SPI口
	spi_sx = open("/dev/spidev1.0", O_RDWR, 0);

    if (spi_sx == -1)
    {
        PyErr_SetFromErrno(PyExc_IOError);
        return NULL;
    }

    // Set mode
    if (ioctl(spi_sx, SPI_IOC_RD_MODE, &mode) == -1)
    {
        PyErr_SetFromErrno(PyExc_IOError);
        close(spi_sx);
        spi_sx = -1;
        return NULL;
    }

    mode = (0x0 & ~(SPI_CPHA | SPI_CPOL)) | mode;

    if (ioctl(spi_sx, SPI_IOC_WR_MODE, &mode) == -1)
    {
        close(spi_sx);
        spi_sx = -1;
        PyErr_SetFromErrno(PyExc_IOError);
        return NULL;
    }

    // Set max speed
    if (ioctl(spi_sx, SPI_IOC_WR_MAX_SPEED_HZ, &max_speed_hz) == -1)
    {
        close(spi_sx);
        spi_sx = -1;
        PyErr_SetFromErrno(PyExc_IOError);
        return NULL;
	}

    // 初始化LoRA模组
    modulationParams.PacketType = PACKET_TYPE_LORA;
	modulationParams.Params.LoRa.SpreadingFactor = LORA_SF9;
	modulationParams.Params.LoRa.Bandwidth = LORA_BW_500;
	modulationParams.Params.LoRa.CodingRate = LORA_CR_4_7;

	PacketParams.PacketType = PACKET_TYPE_LORA;
	PacketParams.Params.LoRa.PreambleLength = 0x08;
	PacketParams.Params.LoRa.HeaderType = LORA_PACKET_VARIABLE_LENGTH;
	PacketParams.Params.LoRa.PayloadLength = 0;
	PacketParams.Params.LoRa.CrcMode = LORA_CRC_ON;
	PacketParams.Params.LoRa.InvertIQ = LORA_IQ_NORMAL;

	sx1262_Init();
	sx1262_SetRegulatorMode(USE_DCDC);

	sx1262_SetStandby(STDBY_XOSC);
	sx1262_SetPacketType(modulationParams.PacketType);
	sx1262_SetModulationParams(&modulationParams);
	sx1262_SetPacketParams(&PacketParams);

	sx1262_SetRfFrequency( RF_FREQUENCY);
	sx1262_SetBufferBaseAddresses(0x00, 0x00);
	sx1262_SetTxParams( TX_OUTPUT_POWER, RADIO_RAMP_20_US);

	sx1262_SetDioIrqParams(RxIrqMask | TxIrqMask, RxIrqMask | TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE);

	sx1262_SetLoRaSymbNumTimeout(0);

    Py_RETURN_NONE;
}

static PyObject * Close(PyObject *self)
{
    close(spi_sx);
    spi_sx = -1;

	Py_RETURN_NONE;
}

// 发送数据
static PyObject * Write(PyObject *self, PyObject * args)
{
	PyObject   *object = NULL;
    Py_buffer   view;

    if (!PyArg_ParseTuple(args, "O", &object))
    {
        return NULL;
    }

    if (PyObject_GetBuffer(object, &view, PyBUF_ANY_CONTIGUOUS | PyBUF_FORMAT) == -1)
    {
        return NULL;
    }

    if (view.ndim != 1)
    {
        printf("Expected a 1-dimensional array\r\n");
        PyBuffer_Release(&view); 
        return NULL;
    }

    /* Check the type of items in the array */
    if (strcmp(view.format, "B") != 0) 
    { 
        printf("Expected an array of byte"); 
        PyBuffer_Release(&view); 
        return NULL; 
    }

    // 写入数据（会在函数内自动进入TX模式）
    PacketParams.Params.LoRa.PayloadLength = (uint8_t)view.len;
	sx1262_SetPacketParams(&PacketParams);
	sx1262_SendPayload((uint8_t*)view.buf, (uint8_t)view.len, 0xFFFF);

    // 等待发送结束（暂定在外部等待）

	Py_RETURN_NONE;
}

// 读取数据，并获得当次数据接收时的RSSI等数据
static PyObject * Read(PyObject *self)
{
    uint8_t     tempBuf[255];       // Max Lora Packet Size
    uint8_t	    size = 0;
    PyObject*   ret;

    sx1262_GetPayload(tempBuf, &size, (uint8_t)sizeof(tempBuf));
    ret = Py_BuildValue("y#", tempBuf, size);
    printf("Receive size=%d\r\n", size);

	return ret;
}

// 读取RSSI和SNR
static PyObject * GetPacketStatus(PyObject *self)
{
    PyObject*   ret;
    int         rssi, snr;

    PacketStatus_t packetStatus;
	sx1262_GetPacketStatus(&packetStatus);
	rssi = packetStatus.Params.LoRa.RssiPkt;
	snr = packetStatus.Params.LoRa.SnrPkt;

    ret = Py_BuildValue("{si,si}", "rssi", rssi, "snr", snr);

    return ret;
}

static PyObject * StartReceive(PyObject *self)
{
    sx1262_SetRxBoosted( 0 );

	Py_RETURN_NONE;
}

static PyObject * EndReceive(PyObject *self)
{
    sx1262_SetStandby(STDBY_XOSC);

	Py_RETURN_NONE;
}

static PyObject * CheckIRQ(PyObject *self)
{
    uint16_t       irqValue = 0;

    // 判断DI0是否有中断，然后在决定读取IRQ寄存器
    if (IRQCheck())
    {
        irqValue = sx1262_ProcessIrqs();
    }

    return Py_BuildValue("i", irqValue);
}

static PyMethodDef sx126x_driverMethods[] = {
    {"Open",  Open, METH_VARARGS, "Open sx126x driver."},
    {"Close", (PyCFunction)Close, METH_NOARGS, "Close sx126x driver."},
    {"Write", Write, METH_VARARGS, "Send data"},
	{"Read", (PyCFunction)Read, METH_NOARGS, "Read data"},
    {"GetPacketStatus", (PyCFunction)GetPacketStatus, METH_NOARGS, "Get packet rssi&snr."},
	{"StartReceive", (PyCFunction)StartReceive, METH_NOARGS, "Start RX, no blocking"},
    {"EndReceive", (PyCFunction)EndReceive, METH_NOARGS, "End RX"},
	{"CheckIRQ", (PyCFunction)CheckIRQ, METH_NOARGS, "Check IRQ, return IRQ type."},
    {NULL, NULL, 0, NULL}        /* Sentinel */
};

static struct PyModuleDef sx126x_drivermodule = {
    PyModuleDef_HEAD_INIT,
    "sx126x_driver",   /* name of module */
    NULL, /* module documentation, may be NULL */
    -1,       /* size of per-interpreter state of the module,
                 or -1 if the module keeps state in global variables. */
    sx126x_driverMethods
};

PyMODINIT_FUNC
PyInit_sx126x_driver(void)
{
    return PyModule_Create(&sx126x_drivermodule);
}

